import { Get, HttpException, Injectable } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { In, Repository } from 'typeorm'
import { User } from './user.entity'
import { Logs } from '../logs/logs.entity'
import { getUserDto } from './dto/get-user.dto'
import { conditionUtils } from '../utils/db.helper'
import { Roles } from '../role/roles.entity'
import * as argon2 from 'argon2'
@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>,
    @InjectRepository(Logs)
    private logsRepository: Repository<Logs>,
    @InjectRepository(Roles)
    private rolesRepository: Repository<Roles>
  ) {}
  @Get()
  async findAll(query: getUserDto): Promise<User[]> {
    const { limit, page, username, gender, role } = query
    const take = limit || 10
    const skip = ((page || 1) - 1) * take
    // SELECT * FROM user u, profile p, role r WHERE u.id = p.uid AND u.id = r.uid AND ....
    // SELECT * FROM user u LEFT JOIN profile p ON u.id = p.uid LEFT JOIN role r ON u.id = r.uid WHERE ....
    // 分页 SQL -> LIMIT 10 OFFSET 10
    const obj = {
      'user.username': username,
      'profile.gender': gender,
      'roles.id': role
    }
    const queryBuilder = this.usersRepository
      .createQueryBuilder('user')
      // .select(['user.id', 'user.username', 'user.email'])
      .leftJoinAndSelect('user.profile', 'profile')
      .leftJoinAndSelect('user.roles', 'roles')
    const newQueryBuilder = conditionUtils<User>(queryBuilder, obj)
    return newQueryBuilder.take(take).skip(skip).getMany()
  }

  async create(user: Partial<User>): Promise<any> {
    if (!user.roles) {
      const role = await this.rolesRepository.findOne({ where: { id: 2 } })
      user.roles = [role]
    }
    if (user.roles instanceof Array && typeof user.roles[0] === 'number') {
      // {id, name} -> { id } -> [id]
      // 查询所有的用户角色
      user.roles = await this.rolesRepository.find({
        where: {
          id: In(user.roles)
        }
      })
    }
    const userTmp = this.usersRepository.create(user)
    userTmp.password = await argon2.hash(userTmp.password)
    await this.usersRepository.save(userTmp)

    return new HttpException('success', 200)
  }
  async update(id: any, user: Partial<User>) {
    const userTemp = await this.findProfile(id)
    console.log(user)
    const newUser = this.usersRepository.merge(userTemp, user)
    return await this.usersRepository.save(newUser)
  }
  async remove(id: number): Promise<any> {
    const user = await this.findOne(id)
    return await this.usersRepository.remove(user)
  }
  findLogsByGroup(id: number): Promise<Logs[]> {
    return this.logsRepository
      .createQueryBuilder('logs')
      .select('logs.status', 'status')
      .addSelect('COUNT(logs.status)', 'count')
      .leftJoinAndSelect('logs.user', 'user')
      .where('user.id = :id', { id })
      .groupBy('logs.status')
      .getRawMany()
  }
  // findOneByUsername
  findByUsername(username: string): Promise<User> {
    return this.usersRepository.findOne({
      where: {
        username
      },
      relations: ['roles']
    })
  }
  findOne(id: number) {
    return this.usersRepository.findOne({ where: { id }, relations: ['roles'] })
  }
  findProfile(id: number): Promise<User> {
    return this.usersRepository.findOne({
      where: {
        id
      },
      relations: {
        profile: true,
        roles: true
      }
    })
  }
}
